<?php

namespace common\service;

use common\model\DepartmentModel;
use common\model\TenantGroupModel;
use common\model\TenantModel;
use common\model\TenantUserDepartmentModel;
use common\model\TenantUserModel;
use support\ErrorCode;
use support\SingletonTrait;
use teamones\Request;
use think\Tree;
use Webman\Stomp\Client;

class DepartmentService
{

    use SingletonTrait;

    /**
     * 创建基础方法
     * @param $data
     * @return array
     * @throws \Exception
     */
    public function create($data)
    {
        // 判断当前
        $tenantModel = model(TenantModel::class);
        $tenant = $tenantModel->where(['id' => $data['tenant_id']])->count();
        if ($tenant <= 0) {
            throw_strack_exception('Tenant does not exist.', ErrorCode::TENANT_NOT_EXIST);
        }

        $departmentModel = model(DepartmentModel::class);
        // 执行新增操作
        $resData = $departmentModel->addItem($data);
        if (!$resData) {
            // 通用创建失败错误码 001
            throw_strack_exception($departmentModel->getError(), ErrorCode::DEPARTMENT_CREATE_FAILURE);
        } else {
            // 返回成功数据
            $this->autoCreateDepartmentChat($resData);
            return $resData;
        }
    }

    /**
     * 部门人员统计
     * @param $param
     * @param $tenantId
     * @param bool $includeEmployed
     * @return array|false|mixed|string
     */
    public function departmentUserCount($param, $tenantId, bool $includeEmployed)
    {
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $fields = $param['fields'] ?? "department.id,department.name,count(distinct tenant_user.id) AS user_count";
        $filter = $param['filter'] ?? [];
        $filter['tenant_user.tenant_id'] = $tenantId;
        $filter['user.is_system'] = "no";
        if (!$includeEmployed) {
            $filter['tenant_user.status'] = ['NEQ', TenantUserModel::STATUS_UNEMPLOYED];
        }

        if (!empty($filter["step_category_id_list"])) {
            $stepCategoryIdList = explode(",", $filter["step_category_id_list"]);
            $stepCategoryIdFilter = [];
            foreach ($stepCategoryIdList as $stepCategoryIdItem) {
                $stepCategoryIdFilter[] = ["step_category_ids" => ["FIND_IN_SET", $stepCategoryIdItem]];
            }

            if (count($stepCategoryIdFilter) > 1) {
                $stepCategoryIdFilter["_logic"] = "OR";
            }
            $filter[] = $stepCategoryIdFilter;
            unset($filter["step_category_id_list"]);
        }

        $departmentUserCount = model(TenantUserModel::class)
            ->join('tenant_user_department on tenant_user.id = tenant_user_department.tenant_user_id')
            ->join('tenant_user_role on tenant_user.id = tenant_user_role.tenant_user_id', 'LEFT')
            ->join('department on department.id = tenant_user_department.department_id')
            ->join("user ON tenant_user.user_id=user.id", 'LEFT')
            ->join("role on role.id = tenant_user_role.role_id", 'LEFT')
            ->field($fields)
            ->where($filter)
            ->group("department.id")
            ->page($page[0], $page[1])
            ->select();

        return $departmentUserCount;
    }

    /**
     * 创建部门聊天
     * @param array $department
     * @throws \Exception
     */
    public function autoCreateDepartmentChat(array $department)
    {
        $chat = [
            'name' => $department['name'],
            'type' => "group",
            'link_id' => $department['id'],
            'link_type' => "department",
            'from_tenant_id' => $department['tenant_id'],
            'to_tenant_id' => 0,
        ];
        $chatUsers = model(TenantUserDepartmentModel::class)
            ->alias('tud')
            ->join('tenant_user tu on tu.id = tud.tenant_user_id')
            ->where([
                'tud.department_id' => $department['id'],
            ])
            ->field("tu.user_id")
            ->column('user_id');
        Client::send('create_chat', build_queue_data_with_xu([
            'chat' => $chat,
            'chat_users' => $chatUsers,
            'owner' => 0
        ]));
    }

    /**
     * 删除部门
     * @param $param
     * @return int
     * @throws \think\Exception|\Throwable
     */
    public function delete($param)
    {
        $departmentModel = model(DepartmentModel::class);
        $departments = $departmentModel->where($param['filter'])->select();
        if (empty($departments)) {
            return 0;
        }
        $departmentTenantId = $departments[0]['tenant_id'];
        $departmentList = model(DepartmentModel::class)->where(['tenant_id' => $departmentTenantId])->select();
        $tree = new Tree('id', 'parent_id', 'children');
        $tree->load($departmentList);
        $deleteDepartmentIdList = [];
        // 查询出要删除的部门id
        foreach ($departments as $department) {
            $deleteDepartmentIdList[$department['id']] = $department['id'];
            $treeData = $tree->DeepTree($department['id']);
            $tree->traverseTree($treeData, function ($item) use (&$deleteDepartmentIdList) {
                $deleteDepartmentIdList[$item['id']] = $item['id'];
            });
        }
        $deleteDepartmentIdList = array_values($deleteDepartmentIdList);
        $count = count($deleteDepartmentIdList);
        if ($count === 0) {
            return 0;
        }
        $this->departmentDeleteCheck($deleteDepartmentIdList);
        $chatService = new ChatService();
        $departmentModel->startTrans();
        try {
            // 删除部门
            $departmentModel->where(['id' => ['IN', $deleteDepartmentIdList]])->delete();
            // 删除部门聊天
            $chatService->deleteChat(['filter' => ['link_type' => 'department', 'link_id' => ['IN', $deleteDepartmentIdList]]]);
            // 查询当前部门的人员
            $tenantUserDepartmentIdList = model(TenantUserDepartmentModel::class)->where(['department_id' => ['IN', $deleteDepartmentIdList]])
                ->field('id')
                ->column('id');
            // 解除部门和用户的关系
            if (count($tenantUserDepartmentIdList) > 0) {
                model(TenantUserDepartmentModel::class)->where(['id' => ['IN', implode(',', $tenantUserDepartmentIdList)]])->delete();
            }
            $departmentModel->commit();
            return $count;
        } catch (\Throwable $e) {
            $departmentModel->rollback();
            throw $e;
        }
    }

    /**
     * 获取部门父级树
     * @param $param
     * @return array
     */
    public function getParentDepartmentList($param)
    {
        $departmentModel = model(DepartmentModel::class);
        $department = $departmentModel->where($param['filter'])->field('id,name,tenant_id,parent_id')->find();
        if (empty($department)) {
            throw_strack_exception('department not exist', ErrorCode::DEPARTMENT_NOT_EXIST);
        }

        $departmentList = $departmentModel->where(['tenant_id' => $department['tenant_id']])->field('id,name,parent_id')->select();
        $departmentList = array_column($departmentList, null, 'id');
        $result = [];
        $this->getParentDepartment($departmentList, $department['id'], $result);
        $result = array_reverse($result);
        return $result;
    }

    public function getParentDepartment($departmentList, $childrenId, &$data)
    {
        if (array_key_exists($childrenId, $departmentList)) {
            $data[] = $departmentList[$childrenId];

            if (array_key_exists($departmentList[$childrenId]['parent_id'], $departmentList)) {
                $this->getParentDepartment($departmentList, $departmentList[$childrenId]['parent_id'], $data);
            }
        }
    }

    /**
     * 获取部门下面的附属部门
     * @param $tenantId
     * @param array $departmentDataIds
     * @return array
     */
    public function getDepartmentUnderChildren($tenantId, array $departmentDataIds)
    {
        if (empty($departmentDataIds)) {
            return [];
        }

        $departmentList = model(DepartmentModel::class)
            ->where(["tenant_id" => $tenantId])
            ->field("id,name,parent_id")
            ->order(['id' => 'DESC'])
            ->select();

        $tree = new Tree("id", "parent_id");
        $tree->load($departmentList);

        //加入部门子集id
        $departmentIds = $departmentDataIds;
        foreach ($departmentDataIds as $departmentId) {
            $childrenDepartmentList = $tree->deepTree($departmentId);
            $tree->traverseTree($childrenDepartmentList, function ($childrenDepartment) use (&$departmentIds) {
                if (!in_array($childrenDepartment['id'], $departmentIds)) {
                    $departmentIds[] = $childrenDepartment['id'];
                }
            });
        }

        return array_unique($departmentIds);
    }

    /**
     * 部门删除检查
     * @param array $deleteDepartmentIdList
     * @return void
     */
    private function departmentDeleteCheck(array $deleteDepartmentIdList)
    {
        // 部门删除检查
        $res = Request::connection()->setServerHost('teamones-olap-sr')
            ->setMethod('POST')
            ->setHeader(['X-Userinfo' => \request()->getXUserInfo()])
            ->setRoute('department/delete_check')
            ->setBody([
                'department_id_list' => $deleteDepartmentIdList
            ])->request();
        $checkRes = array_sum(array_values($res['data']));
        if ($checkRes !== count($deleteDepartmentIdList)) {
            throw_strack_exception('department has task or user, you can`t delete it', ErrorCode::DEPARTMENT_DELETE_CHECK_ERROR_HAS_TASK_OR_USER);
        }
    }

    /**
     * 基础查询
     * @param $param
     * @param $tenantId
     * @return array|false|mixed|string
     */
    public function baseSelect($param, $tenantId)
    {
        $page = $param["page"] ?? [1, C("database.database_max_select_rows")];
        $field = $param["fields"] ?? "*";
        $order = $param["order"] ?? "tenant_id";
        $filter = $param["filter"] ?? [];

        $isQueryTenantGroupDepartment = $filter['is_query_tenant_group_department'] ?? "no";
        unset($filter['is_query_tenant_group_department']);

        //是否查询集团部门
        if ($isQueryTenantGroupDepartment == "yes") {
            //查询该公司的集团
            $tenantGroupTenantIds = model(TenantGroupModel::class)
                ->join("tenant_group_member on tenant_group.id = tenant_group_member.tenant_group_id")
                ->where([
                    'tenant_group.tenant_id' => $tenantId,
                    'tenant_group.status' => "active"
                ])->field("tenant_group_member.tenant_id")->select();

            $tenantGroupTenantIds = array_column($tenantGroupTenantIds, 'tenant_id', "tenant_id");
            if (!empty($tenantGroupTenantIds)) {
                $filter['tenant_id'] = ["IN", join(",", $tenantGroupTenantIds)];
            }
        }

        if (!empty($filter["step_category_id_list"])) {
            $stepCategoryIdList = explode(",", $filter["step_category_id_list"]);
            $stepCategoryIdFilter = [];
            foreach ($stepCategoryIdList as $stepCategoryIdItem) {
                $stepCategoryIdFilter[] = ["step_category_ids" => ["FIND_IN_SET", $stepCategoryIdItem]];
            }

            if (count($stepCategoryIdFilter) > 1) {
                $stepCategoryIdFilter["_logic"] = "OR";
            }
            $filter[] = $stepCategoryIdFilter;
            unset($filter["step_category_id_list"]);
        }

        $departmentList = model(DepartmentModel::class)->where($filter)->field($field)->page(...$page)->order($order)->select();

        if ($isQueryTenantGroupDepartment == "yes") {
            $departmentTenantIds = array_column($departmentList, 'tenant_id', 'tenant_id');
            unset($departmentTenantIds[$tenantId]);
            $tenantList = model(TenantModel::class)->where(["id" => ["IN", join(",", $departmentTenantIds)]])->field("id,name")->select();
            $tenantList = array_column($tenantList, null, 'id');
            foreach ($departmentList as &$departmentItem) {
                if (isset($tenantList[$departmentItem['tenant_id']])) {
                    $departmentItem['tenant'] = $tenantList[$departmentItem['tenant_id']];
                    $departmentItem['tenant']['is_tenant_group'] = isset($tenantGroupTenantIds[$departmentItem['tenant_id']]);
                }
            }
        }

        return $departmentList;
    }

    /**
     * 查询部门用户列表
     * @param $params
     * @return array
     * @throws \Exception
     */
    public function selectUserList($params)
    {
        $fields = $params['fields'] ?? "";
        $filter = $params['filter'] ?? [];
        $filter[] = ['user.phone' => ['NEQ', 'admin']];
        // 如果没有指定筛选什么类型的用户 那么就默认不查询系统用户
        if (!isset($filter['user.is_system'])) {
            $filter['user.is_system'] = 'no';
        }

        //自动加上主表的alias
        if (!empty($fields)) {
            $fields = explode(',', $fields);
        } else {
            $fields = [
                'user.id',
                'user.name',
                'user.phone',
                'user.email',
                'tenant_position.name as tenant_position_name',
                'tenant_position.id as tenant_position_id',
                'tenant_user.id as tenant_user_id',
                'tenant_user.user_id as user_id',
            ];
        }

        $fields = array_map(function ($item) {
            if (!str_contains($item, '.')) {
                $item = "tenant_user." . $item;
            }
            return $item;
        }, $fields);

        $data = model(TenantUserModel::class)
            ->alias("tenant_user")
            ->join("user ON tenant_user.user_id = user.id")
            ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id', 'LEFT')
            ->join('tenant_user_role on tenant_user_role.tenant_user_id = tenant_user.id', 'LEFT')
            ->join("role ON role.id = tenant_user_role.role_id", 'LEFT')
            ->join("department ON department.id = tenant_user_department.department_id", 'LEFT')
            ->join("tenant_position ON tenant_user.tenant_position_id = tenant_position.id", "LEFT")
            ->where($filter)
            ->field(implode(',', $fields))
            ->group('tenant_user.id')
            ->select();

        $tenantUserIdList = array_column($data, 'tenant_user_id');
        $userIdData = array_column($data, 'user_id', 'user_id');
        $avatarMap = [];
        if ($userIdData) {
            $avatarMap = UserService::getInstance()->getUserAvatar($userIdData);
        }
        $tenantUserDepartmentUserInfoList = [];
        if (!empty($tenantUserIdList)) {
            $tenantUserDepartmentUserInfoList = TenantUserService::getInstance()->getTenantUserListDepartmentRole($tenantUserIdList);
        }

        foreach ($data as &$user) {
            $user['avatar'] = "";
            if (isset($avatarMap[$user['user_id']])) {
                $user['avatar'] = $avatarMap[$user['user_id']];
            }
            $user['department_info'] = $user['role_info'] = [];
            if (isset($tenantUserDepartmentUserInfoList[$user['tenant_user_id']])) {
                $user = array_merge($user, $tenantUserDepartmentUserInfoList[$user['tenant_user_id']]);
            }
        }

        return $data;
    }

    /**
     * 部门人员统计
     * @param $param
     * @param $tenantId
     * @param bool $includeEmployed
     * @return array
     * @throws \Exception
     */
    public function departmentUserTree($param, $tenantId, bool $includeEmployed)
    {
        $fields = $param['fields'] ?? "tenant_user.id,user.id,user.name,user.phone,user.email,tenant_user_department.department_id";
        $filter = $param['filter'] ?? [];
        $baseFilter = [
            'tenant_user.tenant_id' => $tenantId,
            'user.is_system' => 'no',
        ];

        if (!$includeEmployed) {
            $baseFilter['tenant_user.status'] = ['NEQ', TenantUserModel::STATUS_UNEMPLOYED];
        }

        // 先通过各种筛选条件查询出部门 然后查询部门用户信息
        $departmentUserCount = model(TenantUserModel::class)
            ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id')
            ->join("department ON department.id = tenant_user_department.department_id")
            ->join("user ON tenant_user.user_id = user.id")
            ->field('department.*')
            ->where($filter)
            ->where($baseFilter)
            ->group('department.id')
            ->select();
        if (empty($departmentUserCount)) {
            return [];
        }
        $userList = model(TenantUserModel::class)
            ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id')
            ->join("user ON tenant_user.user_id = user.id")
            ->where(['tenant_user_department.department_id' => ['IN', array_column($departmentUserCount, 'id')]])
            ->where($baseFilter)
            ->field(build_complex_query_fields(explode(',', $fields), '__'))
            ->select();
        $userList = array_map(function ($item) {
            $item = separate_complex_query_data($item, '__');
            $item['department_id'] = $item['tenant_user_department']['department_id'];
            return $item;
        }, $userList);
        $userList = array_group_by($userList, 'department_id');
        foreach ($departmentUserCount as &$departmentUserCountItem) {
            $departmentUserCountItem['children'] = $userList[$departmentUserCountItem['id']] ?? [];
        }
        return $departmentUserCount;
    }

    /**
     * 返回指定部门基础信息
     * @param $param
     * @return array
     */
    public function getDepartmentList($param)
    {
        if(empty($param)){
            return [];
        }
        $id = implode(',', $param['id']);
        $departmentInfo = model(DepartmentModel::class)
            ->field(['id','name','parent_id'])
            ->where(['id' => ['in', $id]])
            ->select();

        return $departmentInfo;
    }
}
